/*********************************************************************
 * @author kenny 龙前科技
 * @details 请保持文件以UTF-8（无BOM）编码保存
 */

#include <csignal>
#include <execinfo.h>

#include <iostream>

#include <hude/base/log.hpp>
#include <hude/utils/clipp.hpp>

#include "settings.hpp"
#include "service.hpp"

/*********************************************************************
 * @brief 初始化日志实例
 */
hude::logger_default_t _logger;

/*********************************************************************
 * @brief ...
 */
int _main( ha::configs_t& env )
{
    // 初始化全局设置
    {
        auto& s = ha::settings_t::global();

        if( ! env.settings_.empty() && ! s.update( env.settings_.c_str() ) )
        {
            llog_err( "<app>", "error: settings_t::update( %s )", env.settings_.c_str() );
            return -1;
        }
    }

    // 启动守护服务
    {
        ha::service_t service;
        
        auto ret = service.run( env );

        if( 0 != ret )
        {
            llog_err( "<app>", "error: exit service_t::run(), result = %d", ret );
            return ret;
        }
    }

    return 0;
}

/*********************************************************************
 * @brief 打印crash报告
 */
void crash_report( int signum )
{
    const int len = 1024;
    void *func[len];
    char **funs;

    signal(signum, SIG_DFL);

    auto size = backtrace(func, len);
    funs = (char **)backtrace_symbols(func, size);

    fprintf(stderr, "System error, Stack trace:\n");

    for(int i = 0; i < size; ++i)
    {
        fprintf(stderr, "#%d \t %s \n", i, funs[i]);
    }

    free(funs);
}

/*********************************************************************
 * @brief main
 */
int main( int argc, char* argv[] )
{
    ha::configs_t env;

    // Invaild memory address
    signal( SIGSEGV, crash_report );
    // Abort signal
    signal( SIGABRT, crash_report );

    // default env
    {
        env.port_  = 9090U;
        env.debug_ = hude::log_level_t::emDEFAULT;
    }

    // parse format of command line
    auto cli = (
        clipp::option("-p", "--port") & clipp::value("listen port", env.port_ ),
        clipp::option("-s", "--settings") & clipp::value("settings file path", env.settings_ ),
        clipp::option("-D", "--debug") & clipp::value("debug infometion details", env.debug_ )
    );

    if( clipp::parse( argc, argv, cli ) )
    {
        llog( "<app>", "====== %s =====", argv[0] );

        hude::log_debug_info_t::level( static_cast< hude::log_level_t >( env.debug_ ) );

        return _main( env );
    } else {
        std::cout << clipp::make_man_page(cli, argv[0]);
        return -0xffffff;
    }

}
